<!doctypehtml><html class="sidebar-visible no-js light"lang=en><head><meta charset=UTF-8><title>Processing multiple records - Perl One-Liners Guide</title><meta content="text/html; charset=utf-8"http-equiv=Content-Type><meta content="Example based guide for text processing with Perl from the command line"name=description><meta content=width=device-width,initial-scale=1 name=viewport><meta content=#ffffff name=theme-color><meta content="Perl One-Liners Guide"property=og:title><meta content=website property=og:type><meta content="Example based guide for text processing with Perl from the command line"property=og:description><meta content=https://learnbyexample.github.io/learn_perl_oneliners/ property=og:url><meta content=https://raw.githubusercontent.com/learnbyexample/learn_perl_oneliners/main/images/perl_oneliners_ls.png property=og:image><meta content=1280 property=og:image:width><meta content=720 property=og:image:height><meta content=summary_large_image property=twitter:card><meta content=@learn_byexample property=twitter:site><link href="favicon.svg" rel=icon><link rel="shortcut icon"href="favicon.png"><link href="css/variables.css" rel=stylesheet><link href="css/general.css" rel=stylesheet><link href="css/chrome.css" rel=stylesheet><link href="FontAwesome/css/font-awesome.css" rel=stylesheet><link href="fonts/fonts.css" rel=stylesheet><link href="highlight.css" rel=stylesheet><link href="tomorrow-night.css" rel=stylesheet><link href="ayu-highlight.css" rel=stylesheet><link href="style.css" rel=stylesheet><body><script>var path_to_root = "";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";</script><script>try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }</script><script>var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('no-js')
            html.classList.remove('light')
            html.classList.add(theme);
            html.classList.add('js');</script><script>var html = document.querySelector('html');
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);</script><nav aria-label="Table of contents"class=sidebar id=sidebar><div class=sidebar-scrollbox><ol class=chapter><li class="chapter-item expanded affix"><a href="cover.html">Cover</a><li class="chapter-item expanded affix"><a href="buy.html">Buy PDF/EPUB versions</a><li class="chapter-item expanded"><a href="preface.html"><strong aria-hidden=true>1.</strong> Preface</a><li class="chapter-item expanded"><a href="one-liner-introduction.html"><strong aria-hidden=true>2.</strong> One-liner introduction</a><li class="chapter-item expanded"><a href="line-processing.html"><strong aria-hidden=true>3.</strong> Line processing</a><li class="chapter-item expanded"><a href="in-place-file-editing.html"><strong aria-hidden=true>4.</strong> In-place file editing</a><li class="chapter-item expanded"><a href="field-separators.html"><strong aria-hidden=true>5.</strong> Field separators</a><li class="chapter-item expanded"><a href="record-separators.html"><strong aria-hidden=true>6.</strong> Record separators</a><li class="chapter-item expanded"><a href="using-modules.html"><strong aria-hidden=true>7.</strong> Using modules</a><li class="chapter-item expanded"><a href="multiple-file-input.html"><strong aria-hidden=true>8.</strong> Multiple file input</a><li class="chapter-item expanded"><a class=active href="processing-multiple-records.html"><strong aria-hidden=true>9.</strong> Processing multiple records</a><li class="chapter-item expanded"><a href="two-file-processing.html"><strong aria-hidden=true>10.</strong> Two file processing</a><li class="chapter-item expanded"><a href="dealing-with-duplicates.html"><strong aria-hidden=true>11.</strong> Dealing with duplicates</a><li class="chapter-item expanded"><a href="perl-rename-command.html"><strong aria-hidden=true>12.</strong> Perl rename command</a><li class="chapter-item expanded"><a href="Exercise_solutions.html"><strong aria-hidden=true>13.</strong> Exercise Solutions</a></li><br><hr><li class="chapter-item expanded"><i class="fa fa-github"id=git-repository-button></i><a href=https://github.com/learnbyexample/learn_perl_oneliners>   Source code</a><li class="chapter-item expanded"><i class="fa fa-home"id=home-button></i><a href="../index.html">   My Blog</a><li class="chapter-item expanded"><i class="fa fa-book"id=book-button></i><a href="../books.html">   My Books</a><li class="chapter-item expanded"><i class="fa fa-envelope"id=mail-button></i><a href=https://learnbyexample.gumroad.com/l/learnbyexample-weekly>   learnbyexample weekly</a><li class="chapter-item expanded"><i class="fa fa-twitter"id=twitter-button></i><a href=https://twitter.com/learn_byexample>   Twitter</a></ol></div><div class=sidebar-resize-handle id=sidebar-resize-handle></div></nav><div class=page-wrapper id=page-wrapper><div class=page><div id=menu-bar-hover-placeholder></div><div class="menu-bar sticky bordered"id=menu-bar><div class=left-buttons><button aria-label="Toggle Table of Contents"title="Toggle Table of Contents"aria-controls=sidebar class=icon-button id=sidebar-toggle type=button><i class="fa fa-bars"></i></button><button aria-label="Change theme"title="Change theme"aria-controls=theme-list aria-expanded=false aria-haspopup=true class=icon-button id=theme-toggle type=button><i class="fa fa-paint-brush"></i></button><ul aria-label=Themes class=theme-popup id=theme-list role=menu><li role=none><button class=theme id=light role=menuitem>Light (default)</button><li role=none><button class=theme id=rust role=menuitem>Rust</button><li role=none><button class=theme id=coal role=menuitem>Coal</button><li role=none><button class=theme id=navy role=menuitem>Navy</button><li role=none><button class=theme id=ayu role=menuitem>Ayu</button></ul><button aria-label="Toggle Searchbar"title="Search. (Shortkey: s)"aria-controls=searchbar aria-expanded=false aria-keyshortcuts=S class=icon-button id=search-toggle type=button><i class="fa fa-search"></i></button></div><h1 class=menu-title>Perl One-Liners Guide</h1><div class=right-buttons><a aria-label=Blog href="../index.html" title=Blog> <i class="fa fa-home"id=home-button></i> </a><a aria-label=Twitter href=https://twitter.com/learn_byexample title=Twitter> <i class="fa fa-twitter"id=twitter-button></i> </a><a aria-label="Git repository"title="Git repository"href=https://github.com/learnbyexample/learn_perl_oneliners> <i class="fa fa-github"id=git-repository-button></i> </a></div></div><div class=hidden id=search-wrapper><form class=searchbar-outer id=searchbar-outer><input placeholder="Search this book ..."aria-controls=searchresults-outer aria-describedby=searchresults-header id=searchbar name=searchbar type=search></form><div class="searchresults-outer hidden"id=searchresults-outer><div class=searchresults-header id=searchresults-header></div><ul id=searchresults></ul></div></div><script>document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });</script><div class=content id=content><main><div class=sidetoc><nav class=pagetoc></nav></div><h1 id=processing-multiple-records><a class=header href="processing-multiple-records.html#processing-multiple-records">Processing multiple records</a></h1><p>Often, you need to consider multiple lines at a time to make a decision, such as the paragraph mode examples seen earlier. Sometimes, you need to match a particular record and then get records surrounding the matched record. Solution to these type of problems often use state machines. See <a href=https://softwareengineering.stackexchange.com/questions/47806/examples-of-finite-state-machines>softwareengineering: FSM examples</a> if you are not familiar with state machines.<blockquote><p><img alt=info src="images/info.svg"> The <a href=https://github.com/learnbyexample/learn_perl_oneliners/tree/main/example_files>example_files</a> directory has all the files used in the examples.</blockquote><h2 id=processing-consecutive-records><a class=header href="processing-multiple-records.html#processing-consecutive-records">Processing consecutive records</a></h2><p>You might need to define a condition that should satisfy something for one record and something else for the very next record. There are many ways to tackle this problem. One possible solution is to use variables to save the previous records and then create the required conditional expression using those variables and <code>$_</code> which has the current record content.<pre><code class=language-bash># match and print two consecutive records
# the first record should contain 'he' and the second one should contain 'you'
$ perl -ne 'print $p, $_ if /you/ && $p=~/he/; $p = $_' para.txt
Hi there
How are you

# same filtering as above, but print only the first record
$ perl -ne 'print $p if /you/ && $p=~/he/; $p = $_' para.txt
Hi there

# same filtering as above, but print only the second record
$ perl -ne 'print if /you/ && $p=~/he/; $p = $_' para.txt
How are you
</code></pre><h2 id=context-matching><a class=header href="processing-multiple-records.html#context-matching">Context matching</a></h2><p>Sometimes you want not just the matching records, but the records relative to the matches as well. For example, it could be to see the comments at the start of a function block that was matched while searching a program file. Or, it could be to see extended information from a log file while searching for a particular error message.<p>Consider this sample input file:<pre><code class=language-bash>$ cat context.txt
blue
    toy
    flower
    sand stone
light blue
    flower
    sky
    water
language
    english
    hindi
    spanish
    tamil
programming language
    python
    kotlin
    ruby
</code></pre><p><strong>Case 1:</strong> Here's an example that emulates <code>grep --no-group-separator -A&LTn></code> functionality. The <code>$n && $n--</code> trick used in the example below works like this:<ul><li>If initially <code>$n=2</code>, then we get <ul><li><code>2 && 2</code> — evaluates to <code>true</code> and <code>$n</code> becomes <code>1</code><li><code>1 && 1</code> — evaluates to <code>true</code> and <code>$n</code> becomes <code>0</code><li><code>0 && </code> — evaluates to <code>false</code> and <code>$n</code> doesn't change</ul><li>Note that when conditionals are connected with logical <code>&&</code>, the second expression will not be executed at all if the first one turns out to be <code>false</code> because the overall result will always be <code>false</code>. Same is the case if the first expression evaluates to <code>true</code> with the logical <code>||</code> operator. Such logical operators are also known as <strong>short-circuit</strong> operators. Thus, in the above case, <code>$n--</code> won't be executed when <code>$n</code> is <code>0</code> on the left hand side. This prevents <code>$n</code> going negative and <code>$n && $n--</code> will never become <code>true</code> unless <code>$n</code> is assigned again.</ul><pre><code class=language-bash># same as: grep --no-group-separator -A1 'blue'
# print the matching line as well as the one that follows it
$ perl -ne '$n=2 if /blue/; print if $n && $n--' context.txt
blue
    toy
light blue
    flower

# for overlapping cases, $n gets re-assigned before $n becomes 0
$ perl -ne '$n=2 if /toy|flower/; print if $n && $n--' context.txt
    toy
    flower
    sand stone
    flower
    sky
</code></pre><p>Once you've understood the above examples, the rest of the examples in this section should be easier to comprehend. They are all variations of the logic used above and re-arranged to solve the use case being discussed.<p><strong>Case 2:</strong> Print <code>n</code> records after the matching record. This is similar to the previous case, except that the matching record isn't printed.<pre><code class=language-bash># print 2 lines after the matching line
$ perl -ne 'print if $n && $n--; $n=2 if /prog/' context.txt
    python
    kotlin
</code></pre><p><strong>Case 3:</strong> Printing the <code>n</code>th record after the matching record.<pre><code class=language-bash># print only the 3rd line found after the matching line
# $n && !--$n will be true only when --$n yields 0
# overlapping cases won't work as $n gets re-assigned before going to 0
$ perl -ne 'print if $n && !--$n; $n=3 if /language/' context.txt
    spanish
    ruby
</code></pre><p><strong>Case 4:</strong> Printing the matched record and <code>n</code> records before it.<pre><code class=language-bash># print matched record and 2 records before the match
$ perl -ne '$ip[$.]=$_; print @ip[$.-2 .. $.] if /stone/' context.txt
    toy
    flower
    sand stone

# this will work even if there are less than n records before a match
$ n=5 perl -ne '$i=$.-$ENV{n}; $i=0 if $i&LT0; $ip[$.]=$_;
                print @ip[$i .. $.] if /toy/' context.txt
blue
    toy
</code></pre><p>To prevent confusion with overlapping cases, you can add a separation line between the results.<pre><code class=language-bash>$ n=2 perl -ne '$i=$.-$ENV{n}; $i=0 if $i&LT0; $ip[$.]=$_;
                if(/toy|flower/){print $s, @ip[$i .. $.]; $s="---\n"}' context.txt
blue
    toy
---
blue
    toy
    flower
---
    sand stone
light blue
    flower
</code></pre><p><strong>Case 5:</strong> Print <code>n</code>th record before the matching record.<pre><code class=language-bash>$ n=2 perl -ne '$i=$.-$ENV{n}; $i=0 if $i&LT0; $ip[$.]=$_;
                print $ip[$i] if /language/' context.txt
    sky
    spanish

# if the count is small enough, you can save them in variables
# this one prints the 2nd line before the matching line
$ perl -ne 'print $p2 if /toy|flower/; $p2=$p1; $p1=$_' context.txt
blue
    sand stone
</code></pre><p>You can also use the logic from <strong>Case 3</strong> by applying <code>tac</code> twice. This avoids the need to use a hash variable.<pre><code class=language-bash>$ tac context.txt | perl -ne 'print if $n && !--$n; $n=2 if /language/' | tac
    sky
    spanish
</code></pre><h2 id=records-bounded-by-distinct-markers><a class=header href="processing-multiple-records.html#records-bounded-by-distinct-markers">Records bounded by distinct markers</a></h2><p>This section will cover cases where the input file will always contain the same number of starting and ending patterns, arranged in an alternating fashion. For example, there cannot be two starting patterns appearing without an ending pattern between them and vice versa. Lines of text inside and between such groups are optional.<p>The sample file shown below will be used to illustrate examples in this section. For simplicity, assume that the starting pattern is marked by <code>start</code> and the ending pattern by <code>end</code>. They have also been given group numbers to make it easier to analyze the output.<pre><code class=language-bash>$ cat uniform.txt
mango
icecream
--start 1--
1234
6789
**end 1**
how are you
have a nice day
--start 2--
a
b
c
**end 2**
par,far,mar,tar
</code></pre><p><strong>Case 1:</strong> Processing all the groups of records based on the distinct markers, including the records matched by markers themselves. For simplicity, the below command will just print all such records.<pre><code class=language-bash>$ perl -ne '$f=1 if /start/; print if $f; $f=0 if /end/' uniform.txt
--start 1--
1234
6789
**end 1**
--start 2--
a
b
c
**end 2**
</code></pre><blockquote><p><img alt=info src="images/info.svg"> <code>perl -ne 'print if /start/../end/'</code> can be used as seen previously in the <a href="line-processing.html#range-operator">Range operator</a> section. The state machine format is more flexible for the various cases to follow.</blockquote><p><strong>Case 2:</strong> Processing all the groups of records but excluding the records matched by markers themselves.<pre><code class=language-bash>$ perl -ne '$f=0 if /end/; print "* $_" if $f; $f=1 if /start/' uniform.txt
* 1234
* 6789
* a
* b
* c
</code></pre><p><strong>Case 3-4:</strong> Processing all the groups of records but excluding one of the markers.<pre><code class=language-bash>$ perl -ne '$f=1 if /start/; $f=0 if /end/; print if $f' uniform.txt
--start 1--
1234
6789
--start 2--
a
b
c

$ perl -ne 'print if $f; $f=1 if /start/; $f=0 if /end/' uniform.txt
1234
6789
**end 1**
a
b
c
**end 2**
</code></pre><p>The next four cases are obtained by just using <code>if !$f</code> instead of <code>if $f</code> from the cases shown above.<p><strong>Case 5:</strong> Processing all input records except the groups of records bound by the markers.<pre><code class=language-bash># same as: perl -ne 'print if !(/start/../end/)'
$ perl -ne '$f=1 if /start/; print if !$f; $f=0 if /end/' uniform.txt
mango
icecream
how are you
have a nice day
par,far,mar,tar
</code></pre><p><strong>Case 6</strong> Processing all input records except the groups of records between the markers.<pre><code class=language-bash>$ perl -ne '$f=0 if /end/; print if !$f; $f=1 if /start/' uniform.txt
mango
icecream
--start 1--
**end 1**
how are you
have a nice day
--start 2--
**end 2**
par,far,mar,tar
</code></pre><p><strong>Case 7-8:</strong> Similar to case 6, but include only one of the markers.<pre><code class=language-bash>$ perl -ne 'print if !$f; $f=1 if /start/; $f=0 if /end/' uniform.txt
mango
icecream
--start 1--
how are you
have a nice day
--start 2--
par,far,mar,tar

$ perl -ne '$f=1 if /start/; $f=0 if /end/; print if !$f' uniform.txt
mango
icecream
**end 1**
how are you
have a nice day
**end 2**
par,far,mar,tar
</code></pre><h2 id=specific-blocks><a class=header href="processing-multiple-records.html#specific-blocks">Specific blocks</a></h2><p>Instead of working with all the groups (or blocks) bound by the markers, this section will discuss how to choose blocks based on an additional criteria.<p>Here's how you can process only the first matching block. See also <a href=https://stackoverflow.com/q/38481155/4082052>stackoverflow: copy pattern between range only once</a> and <a href=https://stackoverflow.com/a/63072979/4082052>stackoverflow: extract only first range</a>.<pre><code class=language-bash>$ perl -ne '$f=1 if /start/; print if $f; exit if /end/' uniform.txt
--start 1--
1234
6789
**end 1**

# use other tricks discussed in the previous section as needed
$ perl -ne 'exit if /end/; print if $f; $f=1 if /start/' uniform.txt
1234
6789
</code></pre><p>Getting the last block alone involves a lot more work, unless you happen to know how many blocks are present in the input file.<pre><code class=language-bash># reverse input linewise, change the order of comparison, reverse again
# difficult to adjust if the record separator is something other than newline
$ tac uniform.txt | perl -ne '$f=1 if /end/; print if $f; exit if /start/' | tac
--start 2--
a
b
c
**end 2**

# or, save the blocks in a buffer and print the last one alone
$ perl -ne 'if(/start/){$f=1; $buf=$_; next}
            $buf .= $_ if $f;
            $f=0 if /end/;
            END{print $buf}' uniform.txt
--start 2--
a
b
c
**end 2**
</code></pre><p>Only the <code>n</code>th block.<pre><code class=language-bash>$ seq 30 | perl -ne 'BEGIN{$n=2; $c=0} $c++ if /4/; if($c==$n){print; exit if /6/}'
14
15
16
</code></pre><p>All blocks greater than the <code>n</code>th block.<pre><code class=language-bash>$ seq 30 | perl -ne 'BEGIN{$n=1; $c=0} if(/4/){$f=1; $c++}
                     print if $f && $c>$n; $f=0 if /6/'
14
15
16
24
25
26
</code></pre><p>Excluding the <code>n</code>th block.<pre><code class=language-bash>$ seq 30 | perl -ne 'BEGIN{$n=2; $c=0} if(/4/){$f=1; $c++}
                     print if $f && $c!=$n; $f=0 if /6/'
4
5
6
24
25
26
</code></pre><p>All blocks, only if the records between the markers match an additional condition.<pre><code class=language-bash># additional condition here is a record with entire content as '15'
$ seq 30 | perl -ne 'if(/4/){$f=1; $buf=$_; next}
                     $buf .= $_ if $f;
                     if(/6/){$f=0; print $buf if $buf=~/^15$/m}'
14
15
16
</code></pre><h2 id=broken-blocks><a class=header href="processing-multiple-records.html#broken-blocks">Broken blocks</a></h2><p>Sometimes, you can have markers in random order and mixed in different ways. In such cases, to work with blocks without any other marker present in between them, the buffer approach comes in handy again.<pre><code class=language-bash>$ cat broken.txt
qqqqqqqqqqqqqqqq
error 1
hi
error 2
1234
6789
state 1
bye
state 2
error 3
xyz
error 4
abcd
state 3
zzzzzzzzzzzzzzzz

$ perl -ne 'if(/error/){$f=1; $buf=$_; next}
            $buf .= $_ if $f;
            if(/state/){print $buf if $f; $f=0}' broken.txt
error 2
1234
6789
state 1
error 4
abcd
state 3
</code></pre><h2 id=summary><a class=header href="processing-multiple-records.html#summary">Summary</a></h2><p>This chapter covered various examples of working with multiple records. State machines play an important role in deriving solutions for such cases. Knowing various corner cases is also crucial, otherwise a solution that works for one input may fail for others.<p>Next chapter will discuss use cases where you need to process a file input based on contents of another file.<h2 id=exercises><a class=header href="processing-multiple-records.html#exercises">Exercises</a></h2><blockquote><p><img alt=info src="images/info.svg"> The <a href=https://github.com/learnbyexample/learn_perl_oneliners/tree/main/exercises>exercises</a> directory has all the files used in this section.</blockquote><p><strong>1)</strong> For the input file <code>sample.txt</code>, print lines containing <code>do</code> only if the previous line is empty and the line before that contains <code>you</code>.<pre><code class=language-bash>##### add your solution here
Just do-it
Much ado about nothing
</code></pre><p><strong>2)</strong> For the input file <code>sample.txt</code>, match lines containing <code>do</code> or <code>not</code> case insensitively. Each of these terms occur multiple times in the file. The goal is to print only the second occurrences of these terms (independent of each other).<pre><code class=language-bash># for reference, here are all the matches
$ grep -i 'do' sample.txt
Just do-it
No doubt you like it too
Much ado about nothing
$ grep -i 'not' sample.txt
Not a bit funny
Much ado about nothing

##### add your solution here
No doubt you like it too
Much ado about nothing
</code></pre><p><strong>3)</strong> For the input file <code>sample.txt</code>, print the matching line as well as <code>n</code> lines around the matching lines. The value for <code>n</code> is passed to the Perl command as an environment value.<pre><code class=language-bash># match a line containing 'are' or 'bit'
$ n=1 ##### add your solution here
Good day
How are you

Today is sunny
Not a bit funny
No doubt you like it too

# match a line containing 'World'
$ n=2 ##### add your solution here
Hello World

Good day
</code></pre><p><strong>4)</strong> For the input file <code>broken.txt</code>, print all lines between the markers <code>top</code> and <code>bottom</code>. The first Perl command shown below doesn't work because it is matching till the end of file as the second marker isn't found. Assume that the input file cannot have two <code>top</code> markers without a <code>bottom</code> marker appearing in between and vice-versa.<pre><code class=language-bash>$ cat broken.txt
top
3.14
bottom
---
top
1234567890
bottom
top
Hi there
Have a nice day
Good bye

# wrong output
$ perl -ne '$f=0 if /bottom/; print if $f; $f=1 if /top/' broken.txt
3.14
1234567890
Hi there
Have a nice day
Good bye

# expected output
##### add your solution here
3.14
1234567890
</code></pre><p><strong>5)</strong> For the input file <code>concat.txt</code>, extract contents from a line starting with <code>%%% </code> until but not including the next such line. The block to be extracted is indicated by the variable <code>n</code> passed as an environment value.<pre><code class=language-bash>$ cat concat.txt
%%% addr.txt
How are you
This game is good
Today %%% is sunny
%%% broken.txt
top %%%
1234567890
bottom
%%% sample.txt
Just %%% do-it
Believe it
%%% mixed_fs.txt
pink blue white yellow
car,mat,ball,basket

$ n=2 ##### add your solution here
%%% broken.txt
top %%%
1234567890
bottom

$ n=4 ##### add your solution here
%%% mixed_fs.txt
pink blue white yellow
car,mat,ball,basket
</code></pre><p><strong>6)</strong> For the input file <code>perl.md</code>, replace all occurrences of <code>perl</code> (irrespective of case) with <code>Perl</code>. But, do not replace any matches between <code>```perl</code> and <code>```</code> lines (<code>perl</code> in these markers shouldn't be replaced either). Save the output in <code>out.md</code>.<pre><code class=language-bash>##### add your solution here, redirect the output to 'out.md'

$ diff -sq out.md expected.md 
Files out.md and expected.md are identical
</code></pre><p><strong>7)</strong> Print the last two lines for each of the input files <code>ip.txt</code>, <code>sample.txt</code> and <code>table.txt</code>. Also, add a separator between the results as shown below (note that the separator isn't present at the end of the output). Assume that the input files will have at least two lines.<pre><code class=language-bash>##### add your solution here
12345
You are funny
---
Much ado about nothing
He he he
---
blue cake mug shirt -7
yellow banana window shoes 3.14
</code></pre><p><strong>8)</strong> For the input file <code>lines.txt</code>, delete the line that comes after a whole line containing <code>---</code>. Assume that such lines won't occur consecutively.<pre><code class=language-bash>$ cat lines.txt
Go There
come on
go there
---
2 apples and 5 mangoes
come on!
---
2 Apples
COME ON

##### add your solution here
Go There
come on
go there
---
come on!
---
COME ON
</code></pre><p><strong>9)</strong> For the input file <code>result.csv</code>, use <code>---</code> to separate entries with the same name in the first column. Assume that the lines with the same first column value will always be next to each other.<pre><code class=language-bash>$ cat result.csv
Amy,maths,89
Amy,physics,75
Joe,maths,79
John,chemistry,77
John,physics,91
Moe,maths,81
Ravi,physics,84
Ravi,chemistry,70
Yui,maths,92

##### add your solution here
Amy,maths,89
Amy,physics,75
---
Joe,maths,79
---
John,chemistry,77
John,physics,91
---
Moe,maths,81
---
Ravi,physics,84
Ravi,chemistry,70
---
Yui,maths,92
</code></pre></main><nav aria-label="Page navigation"class=nav-wrapper><a aria-label="Previous chapter"class="mobile-nav-chapters previous"title="Previous chapter"aria-keyshortcuts=Left href="multiple-file-input.html" rel=prev> <i class="fa fa-angle-left"></i> </a><a aria-label="Next chapter"class="mobile-nav-chapters next"title="Next chapter"aria-keyshortcuts=Right href="two-file-processing.html" rel=next> <i class="fa fa-angle-right"></i> </a><div style="clear: both"></div></nav></div></div><nav aria-label="Page navigation"class=nav-wide-wrapper><a aria-label="Previous chapter"class="nav-chapters previous"title="Previous chapter"aria-keyshortcuts=Left href="multiple-file-input.html" rel=prev> <i class="fa fa-angle-left"></i> </a><a aria-label="Next chapter"class="nav-chapters next"title="Next chapter"aria-keyshortcuts=Right href="two-file-processing.html" rel=next> <i class="fa fa-angle-right"></i> </a></nav></div><script>window.playground_copyable = true;</script><script charset=utf-8 src="elasticlunr.min.js"></script><script charset=utf-8 src="mark.min.js"></script><script charset=utf-8 src="searcher.js"></script><script charset=utf-8 src="clipboard.min.js"></script><script charset=utf-8 src="highlight.js"></script><script charset=utf-8 src="book.js"></script><script src="sidebar.js"></script>